home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * bbcyl.c
- *
- * This file contains all functions for bounding
- * cylinders used by lathe and sor objects.
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "vector.h"
- #include "povproto.h"
- #include "bcyl.h"
-
-
-
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
-
- static int intersect_thick_cylinder PARAMS((BCYL *BCyl, BCYL_ENTRY *Entry, DBL *dist));
- static void insert_hit PARAMS((BCYL_INT *Element, BCYL_INT *intervals, int *cnt));
- static void intersect_bound_elements PARAMS((BCYL *BCyl, VECTOR P, VECTOR D));
-
-
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_thick_cylinder
- *
- * INPUT
- *
- * BCyl - Pointer to lathe structure
- * Entry - Segment whos bounding cylinder to intersect
- * dist - List of sorted intersection depths
- *
- * OUTPUT
- *
- * RETURNS
- *
- * int - number of intersections found
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Find all intersections of the current ray with the bounding
- * cylinder of the given segment. The intersection tests are
- * done in intersect_bound_elements() and the results stored
- * in the lathe structure are evaluated here.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
-
- static int intersect_thick_cylinder(BCyl, Entry, dist)
- BCYL *BCyl;
- BCYL_ENTRY *Entry;
- DBL *dist;
- {
- int i, j, n;
- DBL k, r, h;
-
- n = 0;
-
- /* Intersect ray with the cap-plane. */
-
- if (BCyl->hint[Entry->h2].n)
- {
- r = BCyl->hint[Entry->h2].w[0];
-
- if ((r >= BCyl->radius[Entry->r1]) &&
- (r <= BCyl->radius[Entry->r2]))
- {
- dist[n++] = BCyl->hint[Entry->h2].d[0];
- }
- }
-
- /* Intersect ray with the base-plane. */
-
- if (BCyl->hint[Entry->h1].n)
- {
- r = BCyl->hint[Entry->h1].w[0];
-
- if ((r >= BCyl->radius[Entry->r1]) &&
- (r <= BCyl->radius[Entry->r2]))
- {
- dist[n++] = BCyl->hint[Entry->h1].d[0];
- }
- }
-
- /* Intersect with inner cylinder. */
-
- if (BCyl->rint[Entry->r1].n)
- {
- h = BCyl->rint[Entry->r1].w[0];
-
- if ((h >= BCyl->height[Entry->h1]) &&
- (h <= BCyl->height[Entry->h2]))
- {
- dist[n++] = BCyl->rint[Entry->r1].d[0];
- }
-
- h = BCyl->rint[Entry->r1].w[1];
-
- if ((h >= BCyl->height[Entry->h1]) &&
- (h <= BCyl->height[Entry->h2]))
- {
- dist[n++] = BCyl->rint[Entry->r1].d[1];
- }
- }
-
- /* Intersect with outer cylinder. */
-
- if (BCyl->rint[Entry->r2].n)
- {
- h = BCyl->rint[Entry->r2].w[0];
-
- if ((h >= BCyl->height[Entry->h1]) &&
- (h <= BCyl->height[Entry->h2]))
- {
- dist[n++] = BCyl->rint[Entry->r2].d[0];
- }
-
- h = BCyl->rint[Entry->r2].w[1];
-
- if ((h >= BCyl->height[Entry->h1]) &&
- (h <= BCyl->height[Entry->h2]))
- {
- dist[n++] = BCyl->rint[Entry->r2].d[1];
- }
- }
-
- /* Sort intersections. */
-
- for (i = 0; i < n; i++)
- {
- for (j = 0; j < n - i - 1; j++)
- {
- if (dist[j] > dist[j+1])
- {
- k = dist[j];
- dist[j] = dist[j+1];
- dist[j+1] = k;
- }
- }
- }
-
- return(n);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_bound_elements
- *
- * INPUT
- *
- * BCyl - Pointer to lathe structure
- * P, D - Current ray
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Intersect all bounding discs and cylinders and store
- * the intersections found in the lathe structure.
- *
- * By intersecting all different discs and cylinders once
- * we avoid testing the same cylinders and discs more than
- * once. This happened when we tested one bounding cylinder
- * after the other.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
-
- static void intersect_bound_elements(BCyl, P, D)
- BCYL *BCyl;
- VECTOR P, D;
- {
- int i;
- DBL a, b, bb, b2, c, d, k;
-
- /* Init constants. */
-
- a = D[X] * D[X] + D[Z] * D[Z];
-
- b = P[X] * D[X] + P[Z] * D[Z];
-
- bb = b * b;
-
- b2 = 2.0 * b;
-
- c = P[X] * P[X] + P[Z] * P[Z];
-
- /* Intersect all rings. */
-
- if ((D[Y] < -EPSILON) || (D[Y] > EPSILON))
- {
- for (i = 0; i < BCyl->nheight; i++)
- {
- k = (BCyl->height[i] - P[Y]) / D[Y];
-
- BCyl->hint[i].n = 1;
-
- BCyl->hint[i].d[0] = k;
-
- BCyl->hint[i].w[0] = k * (a * k + b2) + c;
- }
- }
- else
- {
- for (i = 0; i < BCyl->nheight; i++)
- {
- BCyl->hint[i].n = 0;
- }
- }
-
- /* Intersect all cylinders. */
-
- for (i = 0; i < BCyl->nradius; i++)
- {
- BCyl->rint[i].n = 0;
-
- if (BCyl->radius[i] > EPSILON)
- {
- d = bb - a * (c - BCyl->radius[i]);
-
- if (d > 0.0)
- {
- d = sqrt(d);
-
- k = (-b + d) / a;
-
- BCyl->rint[i].n = 2;
-
- BCyl->rint[i].d[0] = k;
-
- BCyl->rint[i].w[0] = P[Y] + k * D[Y];
-
- k = (-b - d) / a;
-
- BCyl->rint[i].d[1] = k;
-
- BCyl->rint[i].w[1] = P[Y] + k * D[Y];
- }
- }
- }
- }
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * insert_hit
- *
- * INPUT
- *
- * element - Intersection to insert
- * intervals - List of intervals
- * cnt - Number of elements in the list
- *
- * OUTPUT
- *
- * intervals, cnt
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Insert an intersection into the depth sorted intersection list.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
-
- static void insert_hit(element, intervals, cnt)
- BCYL_INT *element, *intervals;
- int *cnt;
- {
- int k;
-
- intervals[*cnt] = *element;
-
- for (k = 0; element->d[0] > intervals[k].d[0]; k++);
-
- if (k < *cnt)
- {
- POV_MEMMOVE(&intervals[k+1], &intervals[k], (*cnt-k)*sizeof(BCYL_INT));
-
- intervals[k] = *element;
- }
-
- (*cnt)++;
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Intersect_All_Bounds
- *
- * INPUT
- *
- * BCyl - Pointer to lathe structure
- * P, D - Current ray
- * intervals - List of intervals
- * cnt - Number of elements in the list
- *
- * OUTPUT
- *
- * intervals, cnt
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Intersect given ray with all bounding cylinders of the given lathe
- * and return a sorted list of intersection depths and segments hit.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
-
- int Intersect_BCyl(BCyl, P, D)
- BCYL *BCyl;
- VECTOR P, D;
- {
- int i, cnt;
- DBL dist[8];
- BCYL_INT Inter;
- BCYL_INT *intervals;
- BCYL_ENTRY *Entry;
-
- cnt = 0;
-
- Inter.d[1] = 0.0;
-
- /* Intersect all cylinder and plane elements. */
-
- intersect_bound_elements(BCyl, P, D);
-
- /* Intersect all spline segments. */
-
- intervals = BCyl->intervals;
-
- for (i = 0; i < BCyl->number; i++)
- {
- Entry = &BCyl->entry[i];
-
- switch (intersect_thick_cylinder(BCyl, Entry, dist))
- {
- case 2:
-
- if (dist[0] > EPSILON)
- {
- Inter.d[0] = dist[0];
- Inter.n = i;
-
- insert_hit(&Inter, intervals, &cnt);
- }
- else
- {
- if (dist[1] > EPSILON)
- {
- Inter.d[0] = 0.0;
- Inter.n = i;
-
- insert_hit(&Inter, intervals, &cnt);
- }
- }
-
- break;
-
- case 4:
-
- if (dist[0] > EPSILON)
- {
- Inter.d[0] = dist[0];
- Inter.n = i;
-
- insert_hit(&Inter, intervals, &cnt);
- }
- else
- {
- if (dist[1] > EPSILON)
- {
- Inter.d[0] = 0.0;
- Inter.n = i;
-
- insert_hit(&Inter, intervals, &cnt);
- }
- else
- {
- if (dist[2] > EPSILON)
- {
- Inter.d[0] = dist[2];
- Inter.n = i;
-
- insert_hit(&Inter, intervals, &cnt);
- }
- else
- {
- if (dist[3] > EPSILON)
- {
- Inter.d[0] = 0.0;
- Inter.n = i;
-
- insert_hit(&Inter, intervals, &cnt);
- }
- }
- }
- }
-
- break;
-
- default:
-
- /*
- * We weren't able to find an even number of intersections. Thus
- * we can't tell where the ray enters and leaves the bounding
- * cylinder. To avoid problems we assume that the ray is always
- * inside the cylinder in that case.
- */
-
- Inter.d[0] = dist[0];
- Inter.n = i;
-
- insert_hit(&Inter, intervals, &cnt);
-
- break;
- }
- }
-
- return(cnt);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_BCyl
- *
- * INPUT
- *
- * number - number of cylindrical segments
- * r1, r2 - list of segment radii
- * h1, h2 - list of segment heights
- *
- * OUTPUT
- *
- * RETURNS
- *
- * BCYL * - created bounding cylinder.
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Create a bounding cylinder data structure from the given
- * radii and heights.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
-
- BCYL *Create_BCyl(number, tmp_r1, tmp_r2, tmp_h1, tmp_h2)
- int number;
- DBL *tmp_r1, *tmp_r2, *tmp_h1, *tmp_h2;
- {
- int i, j, nr, nh;
- int *tmp_r1_index;
- int *tmp_r2_index;
- int *tmp_h1_index;
- int *tmp_h2_index;
- DBL *tmp_radius;
- DBL *tmp_height;
- BCYL *bcyl;
-
- /* Allocate bounding cylinder. */
-
- bcyl = (BCYL *)POV_MALLOC(sizeof(BCYL), "bounding cylinder");
-
- /* Allocate entries. */
-
- bcyl->number = number;
-
- bcyl->entry = (BCYL_ENTRY *)POV_MALLOC(bcyl->number*sizeof(BCYL_ENTRY), "bounding cylinder data");
-
- /* Allocate intersection lists. */
-
- bcyl->hint = (BCYL_INT *)POV_MALLOC(2*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
- bcyl->rint = (BCYL_INT *)POV_MALLOC(2*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
-
- bcyl->intervals = (BCYL_INT *)POV_MALLOC(4*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
-
- /* Allocate temporary lists. */
-
- tmp_r1_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
- tmp_r2_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
- tmp_h1_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
- tmp_h2_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
-
- tmp_radius = (DBL *)POV_MALLOC(2 * bcyl->number * sizeof(DBL), "temp lathe data");
- tmp_height = (DBL *)POV_MALLOC(2 * bcyl->number * sizeof(DBL), "temp lathe data");
-
- /* Get different bounding radii and heights. */
-
- nr = 0;
- nh = 0;
-
- for (i = 0; i < bcyl->number; i++)
- {
- tmp_r1_index[i] = -1;
- tmp_r2_index[i] = -1;
- tmp_h1_index[i] = -1;
- tmp_h2_index[i] = -1;
-
- for (j = 0; j < nr; j++)
- {
- if (tmp_r1[i] == tmp_radius[j])
- {
- break;
- }
- }
-
- if (j == nr)
- {
- tmp_radius[nr++] = tmp_r1[i];
- }
-
- tmp_r1_index[i] = j;
-
- for (j = 0; j < nr; j++)
- {
- if (tmp_r2[i] == tmp_radius[j])
- {
- break;
- }
- }
-
- if (j == nr)
- {
- tmp_radius[nr++] = tmp_r2[i];
- }
-
- tmp_r2_index[i] = j;
-
- for (j = 0; j < nh; j++)
- {
- if (tmp_h1[i] == tmp_height[j])
- {
- break;
- }
- }
-
- if (j == nh)
- {
- tmp_height[nh++] = tmp_h1[i];
- }
-
- tmp_h1_index[i] = j;
-
- for (j = 0; j < nh; j++)
- {
- if (tmp_h2[i] == tmp_height[j])
- {
- break;
- }
- }
-
- if (j == nh)
- {
- tmp_height[nh++] = tmp_h2[i];
- }
-
- tmp_h2_index[i] = j;
- }
-
- /* Copy lists into the lathe. */
-
- bcyl->radius = (DBL *)POV_MALLOC(nr * sizeof(DBL), "bounding cylinder data");
- bcyl->height = (DBL *)POV_MALLOC(nh * sizeof(DBL), "bounding cylinder data");
-
- for (i = 0; i < nr; i++)
- {
- bcyl->radius[i] = Sqr(tmp_radius[i]);
- }
-
- for (i = 0; i < nh; i++)
- {
- bcyl->height[i] = tmp_height[i];
- }
-
- /* Assign height and radius indices. */
-
- bcyl->nradius = nr;
- bcyl->nheight = nh;
-
- for (i = 0; i < bcyl->number; i++)
- {
- bcyl->entry[i].r1 = tmp_r1_index[i];
- bcyl->entry[i].r2 = tmp_r2_index[i];
- bcyl->entry[i].h1 = tmp_h1_index[i];
- bcyl->entry[i].h2 = tmp_h2_index[i];
- }
-
- /*
- fprintf(stderr, "number of different radii = %d\n", nr);
- fprintf(stderr, "number of different heights = %d\n", nh);
- */
-
- /* Get rid of temp. memory. */
-
- POV_FREE(tmp_height);
- POV_FREE(tmp_radius);
- POV_FREE(tmp_h2_index);
- POV_FREE(tmp_h1_index);
- POV_FREE(tmp_r2_index);
- POV_FREE(tmp_r1_index);
-
- return(bcyl);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_BCyl
- *
- * INPUT
- *
- * BCyl - bounding cylinder
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Destroy a bounding cylinder.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
-
- void Destroy_BCyl(BCyl)
- BCYL *BCyl;
- {
- POV_FREE(BCyl->entry);
-
- POV_FREE(BCyl->radius);
-
- POV_FREE(BCyl->height);
-
- POV_FREE(BCyl->rint);
-
- POV_FREE(BCyl->hint);
-
- POV_FREE(BCyl->intervals);
-
- POV_FREE(BCyl);
- }
-
-
-
-